/*
 *  Copyright 2001-2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package ar.uba.fi.posgrado.economy.service;

import java.util.List;

import ar.uba.fi.posgrado.common.exception.MissingArgumentException;
import ar.uba.fi.posgrado.common.exception.PosgradoException;
import ar.uba.fi.posgrado.common.exception.PosgradoRuntimeException;
import ar.uba.fi.posgrado.common.service.GenericService;
import ar.uba.fi.posgrado.economy.exception.CollectRuleException;
import ar.uba.fi.posgrado.economy.model.CustomerAccount;
import ar.uba.fi.posgrado.economy.model.Collect;
import ar.uba.fi.posgrado.economy.model.CollectType;

/**
 * Servicio para {@link Collect cobro} y {@link CollectType tipos de cobro}.<br>
 * 
 * @author nicolas.gonzalez
 * 
 * @see GenericService
 */
public interface CollectService extends GenericService<Collect> {

    /**
     * Busca los {@link CollectType}s
     * @return
     * @throws PosgradoRuntimeException
     * @throws PosgradoException
     */
    public List<CollectType> getAllCollectTypes() throws PosgradoRuntimeException, PosgradoException;

    /**
     * Busca el {@link CollectType} por id
     * @param collectTypeId
     * @return
     * @throws PosgradoRuntimeException
     * @throws PosgradoException
     */
    public CollectType getCollectTypeById(Long collectTypeId) throws PosgradoRuntimeException, PosgradoException;
    
    /**
     * Aplica ciertas reglas:<br>
     * <ul> 
     *  <li>Si el valor del cobro es mayor que el de la deuda entonces lo deja en saldo de la cta cte, y el saldo de la deuda es cero</li>
     *  <li>Si el valor es menor q el del cobro, entonces modifica la deuda dejando en el saldo de la misma la diferencia</li>
     *  <li>Si el valor es igual deja cero en saldo de la deuda</li>
     * </ul>
     * <br>
     * Siempre se modifica el estado de la deuda de alguna manera.<br><br>
     * 
     * El valor de la deuda con el cual se compara es el valor menos descuentos y beneficios (si correspondiera...).<br><br>
     * 
     * Este servicio <b>NO</b> aplica para <b>Ajustes</b>, esto es:<br>
     * <i>Si se registra un cobro para dejar dinero en la cta cte o para modificar un cobro...</i><br><br>
     * 
     * El credito a favor que hubiere en la <b>cuenta corriente NO</b> se utiliza para el cobro.<br>
     * 
     * Se actualiza la cuenta corriente modificando la deuda total.<br>
     * 
     * @see ar.uba.fi.posgrado.common.service.GenericService#create(java.lang.Object)
     */
    public void create(Collect collect) throws MissingArgumentException, CollectRuleException, PosgradoException;
    // Se sobreescribe porq hace bastantes acciones necesarias de comentar
    
    /**
     * Busca la deuda y cliente por id
     * @see #create(Collect)
     */
    public void create(Collect collect, Long debtId, Long customerId) throws MissingArgumentException, CollectRuleException, PosgradoException;
    
    /**
     * Busca la deuda y cliente por id.<br>
     * <b>Se usa el valor de cobro q da de la suma de ammountFromAccount + collect.value.</b><br><br>
     * 
     * Si ammountFromAccount es mayor a lo que tiene la cuenta corriente entonces falla.<br>
     * 
     * <b>IMPORTANTE</b>: Quien invoca el servicio NO puede permitir que se adicione dinero extra
     * y a la vez se use de la cta a favor.<br> En ese caso falla este servicio.<br>
     * 
     */
    public void create(Collect collect, Long debtId, Long customerId, Double amountFromAccount) throws MissingArgumentException, CollectRuleException, PosgradoException;
    
    
    /**
     * Operacion <b>NO PERMITIDA</b>.<br>
     * No se pueden modificar los cobros.<br>
     * Arroja un CollectRuleException <b>SIEMPRE</b>.<br><br>
     * 
     * @see ar.uba.fi.posgrado.common.service.GenericService#update(java.lang.Object)
     */
    public Collect update(Collect collect) throws PosgradoRuntimeException, CollectRuleException, PosgradoException;    
    
    /**
     * Operacion <b>NO PERMITIDA</b>.<br>
     * No se pueden eliminar los cobros.<br>
     * Arroja un CollectRuleException <b>SIEMPRE</b>.<br><br>
     * 
     * @see ar.uba.fi.posgrado.common.service.GenericService#delete(java.lang.Object)
     */
    public void delete(Collect t) throws PosgradoRuntimeException, CollectRuleException, PosgradoException;
    
    
    /**
     * Devuelve una lista de {@link Collect Cobros}  por cualquiera de los atributos del
     * cobro recibido por parametro.<br><br>
     * 
     * <b>Importante: </b>
     * Los resultados estan ordenados por el cliente y la fecha.<br><br>
     * 
     * La fecha se usa como Menor o Igual.<br>
     * 
     * @param collect
     * @return
     * @throws PosgradoRuntimeException
     * @throws PosgradoException
     */
    public List<Collect> getCollectsByConditions(Collect collect) throws PosgradoRuntimeException, PosgradoException;
    
    
    /**
     * Devuelve lo maximo que se puede usar que habia en la cta cte.<br>
     * 
     * @param account
     * @return
     * @throws PosgradoRuntimeException
     * @throws PosgradoException
     */
    public Double getMaximumAvailable(CustomerAccount account) throws PosgradoRuntimeException, PosgradoException;
    
}
